package leetcode;

import java.util.ArrayList;
import java.util.List;

/**
 * 给出一个链表，每 k 个节点一组进行翻转，并返回翻转后的链表。
 *
 * k 是一个正整数，它的值小于或等于链表的长度。如果节点总数不是 k 的整数倍，那么将最后剩余节点保持原有顺序。
 *
 * 示例 :
 *
 * 给定这个链表：1->2->3->4->5
 *
 * 当 k = 2 时，应当返回: 2->1->4->3->5
 *
 * 当 k = 3 时，应当返回: 3->2->1->4->5
 *
 * 说明 :
 *
 * 你的算法只能使用常数的额外空间。
 * 你不能只是单纯的改变节点内部的值，而是需要实际的进行节点交换。
 */
public class Code25 {
    public static void main(String[] args) {
        List<Integer> list = ListNode.createArr(
                new Code25().reverseKGroup(ListNode.createListNode(new int[]{1,2,3,4,5,6,7,8,9}),3)
        );
        for (Integer i:list){
            System.out.print(i+" ");
        }
        System.out.println();
    }


    /**
     * 递归的思想
     * @param head
     * @param k
     * @return
     */
    public ListNode reverseKGroup(ListNode head, int k) {
        if(head==null) return head;
        ListNode vHead = head;
        int cnt=0;
        while (head!=null&&cnt<k){
            head=head.next;
            cnt++;
        }
        ListNode nextHead = head;
        if(cnt==k){
            cnt--;
            nextHead= reverseKGroup(nextHead,k);
            ListNode item;
            while(cnt>=0&&vHead!=null){
                item = vHead.next;
                vHead.next=nextHead;
                nextHead=vHead;
                vHead=item;
                cnt--;
            }
            vHead=nextHead;
        }
        return vHead;
    }

    public ListNode reverseKGroup2(ListNode head, int k) {
        if (head==null||getNodeList(head)<k){
            return head;
        }
        ListNode init = new ListNode(-1);
        ListNode before = init;
        ListNode vHead = head;
        while(before!=null){
            ArrayList<ListNode> needChangeNode = new ArrayList<>();
            for(int a=0;a<k&&vHead!=null;a++){
                needChangeNode.add(vHead);
                vHead=vHead.next;
            }
            if(needChangeNode.size()==k) {
                ListNode newHead = reverseNodeList(needChangeNode);
                before.next = newHead;
                before = needChangeNode.get(0);
            }else{
                break;
            }
        }
        return init.next;
    }

    private int getNodeList(ListNode head) {
        ListNode vHead=head;
        int a=0;
        while(vHead!=null){
            vHead=vHead.next;
            a++;
        }
        return a;
    }

    public ListNode reverseNodeList(List<ListNode> listNodes){
        for (int a=0;a<listNodes.size();a++){
            ListNode item = listNodes.get(a);
            if(a==0){
                item.next=listNodes.get(listNodes.size()-1).next;
            }else{
                item.next=listNodes.get(a-1);
            }
        }
        return listNodes.get(listNodes.size()-1);
    }
}
